package com.ge.pp;

import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Vector;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;


public class PPViewer extends WindowAdapter implements ActionListener, TreeSelectionListener 
{
	/*
	 * Ravi      :  Checked
	 */
	public void windowClosing(WindowEvent arg0) 
	{		
		try
		{
			System.out.println("WindowClosing : in ");
			super.windowClosing(arg0);
			mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			CleanupAndExit();
		}
		catch(Exception e)
		{
			try {
				throw e;
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
	/*
	 * Ravi      :  Checked
	 */
	private void CleanupAndExit() throws Exception 
	{
		try
		{System.out.println("CleanupAndExit : in");
		if (serverConnection != null) 
		{
			CheckinCases();		
			serverConnection.Disconnect();
		}
		mainFrame.dispose();
		System.out.println("bye");
		System.exit(0);
		}
		catch(Exception e)
		{
			throw e;
		}
	}
    /*
     * Ravi   :  checked
     */
	public void CheckinCases() throws Exception 
	{
		try
		{
		System.out.println("CheckinCases : in");
		DefaultMutableTreeNode root = (DefaultMutableTreeNode)treeModel.getRoot();
		int childCount = root.getChildCount();
		for(int i=0; i<childCount; i++) 
		{
			DefaultMutableTreeNode node = (DefaultMutableTreeNode)root.getChildAt(i);
			if (!node.isLeaf()) 
			{
				Case c= (Case)node.getUserObject();
				serverConnection.CheckinCase(c);
			}
		}
		}
		catch(Exception e)
		{
			throw e;
		}
	}

	JFrame mainFrame = null;
	private JTree caseTree;
	private PicturePane picturePane;
	private Socket clientSocket;
	private PPServerConnection serverConnection=null;
	private Vector caseList;
	private JMenuItem connectServerItem;
	private DefaultMutableTreeNode rootNode;
	private DefaultTreeModel treeModel;
	public Vector<ImageFilter> imageFilters;
	/*
	 * Ravi :checked
	 */
	public PPViewer() throws Exception 
	{
		try
		{System.out.println("PPViewer constuctor called");
		caseList= new Vector<Case>();		
		
		mainFrame = new JFrame();
		mainFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		mainFrame.addWindowListener(this);
		// I add this  
		//mainFrame.setSize(500,300);
		//mainFrame.setLocation(80,20);
		initMenus();
				
		//Create the nodes.
        rootNode = new DefaultMutableTreeNode("Open Case List");
        treeModel = new DefaultTreeModel(rootNode);
        
        //Create a tree that allows one selection at a time.
        caseTree = new JTree(treeModel);
        caseTree.setEditable(true);
        caseTree.getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);        
        
        //Listen for when the selection changes.
        caseTree.addTreeSelectionListener(this);        

        //Create the scroll pane and add the tree to it. 
        JScrollPane caseTreePane = new JScrollPane(caseTree);
		
        JScrollPane pictureViewPane = new JScrollPane();
        picturePane = new PicturePane(this);
        
		JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, caseTreePane, picturePane);
		Dimension minimumSize = new Dimension(200, 50);
		caseTreePane.setMinimumSize(minimumSize);
		minimumSize = new Dimension(300,300);
        picturePane.setMinimumSize(minimumSize);
        splitter.setDividerLocation(100);         
        splitter.setPreferredSize(new Dimension(800, 800)); //here we change the size of the viewer
        
		Container mainContent = mainFrame.getContentPane();
		mainContent.add(splitter);
		
		mainFrame.pack();
		mainFrame.setVisible(true);
		System.out.println("PPViewer constuctor exit");
		}
		catch(Exception e)
		{
			throw e;
		}
	}
	/*
	 * Ravi : checked
	 */
	private void initMenus() throws Exception {
		try
		{
		System.out.println("initMenus    : in");
		JMenuBar menuBar = new JMenuBar();
		// Server menu
		JMenu menu = new JMenu("Server");
		menuBar.add(menu);
	
		connectServerItem = new JMenuItem("Connect to Server"); // OK fine
		connectServerItem.addActionListener(this);
		
		JMenuItem disconnectServerItem = new JMenuItem("Disconnect");    // OK fine
		disconnectServerItem.addActionListener(this);
		
		JSeparator sep = new JSeparator();		
		
		JMenuItem quitItem = new JMenuItem("Quit");   //Ok fine
		quitItem.addActionListener(this);
		
		menu.add(connectServerItem);
		menu.add(disconnectServerItem);
		menu.add(sep);
		
		menu.add(quitItem);
		
		// Cases
		JMenu caseMenu = new JMenu("Case");
		JMenuItem openCaseItem = new JMenuItem("Open Case");  //
		openCaseItem.addActionListener(this);
		
		JMenuItem closeCaseItem = new JMenuItem("Close Case"); //
		closeCaseItem.addActionListener(this);
		
		JMenuItem referCaseItem = new JMenuItem("Refer Case");  // 
		referCaseItem.addActionListener(this);
		
		caseMenu.add(openCaseItem);
		caseMenu.add(closeCaseItem);
		caseMenu.add(referCaseItem);
		
		menuBar.add(caseMenu);
		
		// Filters
		JMenu filterMenu = new JMenu("Filters");
		JMenuItem setFilter = new JMenuItem("Set Filter");
		setFilter.addActionListener(this);		
		filterMenu.add(setFilter);		
		JMenuItem configFilter = new JMenuItem("Configure Filter");
		configFilter.addActionListener(this);		
		filterMenu.add(configFilter);			
		menuBar.add(filterMenu);
		
		mainFrame.setJMenuBar(menuBar);
		}
		catch(Exception e)
		{
			throw e;
		}
	}

	public class FilterConfig extends JDialog implements ChangeListener, ActionListener
	{
		
		ImageFilter filter;
		HashMap<JSlider, FilterAttribute> sliderMap;
		
		public FilterConfig(JFrame parent, ImageFilter f) throws Exception {
			
			super(parent, "Filter Configuration", true);
			try
			{
			filter = f;
			sliderMap = new HashMap<JSlider, FilterAttribute>();
			
			Vector<FilterAttribute> attrs = filter.getAttributes();
			
			Container cp = getContentPane();
			GridLayout mainLayout = new GridLayout(attrs.size()+1, 2);
			cp.setLayout(mainLayout);
			
			for(FilterAttribute fa : attrs) {
				cp.add(new JLabel(fa.name));
				int v = (int)(((fa.val-fa.min)/(fa.max-fa.min))*1000);
				JSlider valSlider = new JSlider(0, 1000, v);
				cp.add(valSlider);
				sliderMap.put(valSlider, fa);
				valSlider.addChangeListener(this);
			}		
			
			JButton closeBtn = new JButton("Close");
			cp.add(closeBtn);
			closeBtn.addActionListener(this);
			pack();
			}
			catch(Exception e)
			{
				throw e;
			}
		}

		@Override
		public void stateChanged(ChangeEvent e) {
			try
			{
			JSlider slider= (JSlider)e.getSource();
			FilterAttribute fa = sliderMap.get(slider);
			float v = slider.getValue();			
			fa.set(v*((fa.max-fa.min)/1000)+fa.min);
			filter.refresh();
			}
			catch(Exception ex)
			{
				try {
					throw ex;
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}

		@Override
		public void actionPerformed(ActionEvent arg0) {
			try
			{
				dispose();
			}
			catch(Exception e)
			{
				try {
					throw e;
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
	}
	/*
	 * Ravi : checked
	 */
	public static void doGUI() throws Exception 
	{
		try
		{
		System.out.println(" doGUI  : in ");
		// Use the Java look and feel.
        try 
        {
            UIManager.setLookAndFeel
            (
                UIManager.getCrossPlatformLookAndFeelClassName());
        } catch (Exception e) { }

        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);
        JDialog.setDefaultLookAndFeelDecorated(true);
        PPViewer p = new PPViewer();
        }
		catch(Exception e)
		{
			throw e;
		}
		//PPviewer object created.        
	}
	
	/**
	 * Ravi : Checked
	 */
	public static void main(String[] args) 
	{
		System.out.println(" main  : in ");
		javax.swing.SwingUtilities.invokeLater(new Runnable() 
		{
            public void run() 
            {
                try {
					doGUI();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }
        });
	}

	@Override
	public void actionPerformed(ActionEvent e) 
	{
		try
		{System.out.println("actionPerformed"); 
		String command = e.getActionCommand();
		if(command.equals("Quit")) 
		{
			handleQuit();
		} 
		else if (command.equals("Show Image")) 
		{		
			// Just for debugging			
		} 
		else if (command.equals("Connect to Server")) 
		{
			handleServerConnect();
		} 
		else if (command.equals("Disconnect")) 
		{
			if (serverConnection != null) {
				CheckinCases();
				
				DefaultMutableTreeNode root = (DefaultMutableTreeNode)treeModel.getRoot();
				//NEW Change
				int totalChild = root.getChildCount();
				for(int i=0; i< totalChild; i++) {				
					DefaultMutableTreeNode node = (DefaultMutableTreeNode)root.getChildAt(0);
					treeModel.removeNodeFromParent(node);
				}
				connectServerItem.setEnabled(true);	
				serverConnection.Disconnect();				
				serverConnection = null;
				picturePane.ShowImage(null, null);
			}
		} 
		else if (command.equals("Open Case")) 
		{
			openCase();			
		} 
		else if (command.equals("Close Case")) 
		{
			closeCase();
		} 
		else if (command.equals("Refer Case")) 
		{
			referCase();
		} 
		else if (command.equals("Configure Filter")) {
			showFilterConfig();
		} 
		else if (command.equals("Set Filter")) {
			showFilterList();
		}
		}
		catch(Exception ex)
		{
			try {
				throw ex;
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

	private void referCase() throws Exception 
	{		
		
		try
		{
			System.out.println("refercase");
		Vector<String> refDocs = serverConnection.GetReferringDocs();
		if(refDocs.size() > 0) 
		{
			
			int numDocs = refDocs.size();
			String [] docNames = new String[numDocs];
			System.out.println(numDocs);
			for(int i=0; i<numDocs; i++) 
			{
				docNames[i] = refDocs.get(i);
			}
			String docName = "";
			
			String option = (String) JOptionPane.showInputDialog(mainFrame, "Select Doctor", "", JOptionPane.PLAIN_MESSAGE, null, 
					docNames, docName);
			if (option != null) 
			{
				docName = option;
			}
			
			DefaultMutableTreeNode node = (DefaultMutableTreeNode)caseTree.getLastSelectedPathComponent();
			if(node != null && !node.isLeaf() && !node.isRoot()) {
				System.out.println(docName);
				// Case node
				Case c = (Case)node.getUserObject();
				treeModel.removeNodeFromParent(node);
				serverConnection.ReferCase(c, docName);
			}
		}
		}
		catch(Exception ex)
		{
			throw ex;
		}
	}

	private void showFilterList() throws Exception 
	{
		try
		{
			System.out.println("showFilterList : in");
		int numFilters = picturePane.filterList.size();
		String [] filterNames = new String[numFilters+1];
		filterNames[0] = "None";
		for(int i=0; i<numFilters; i++) {
			filterNames[i+1] = picturePane.filterList.get(i).name;
		}
		String curFilter = "";
		if(picturePane.filter != null)
			curFilter = picturePane.filter.name;
		
		String option = (String) JOptionPane.showInputDialog(mainFrame, "Select Filter", "", JOptionPane.PLAIN_MESSAGE, null, 
				filterNames, curFilter);
		if (option != null) 
		{
			if (option.equals("None"))
				picturePane.setFilter(null);
			else
				picturePane.setFilter(option);
		}
		}
		catch(Exception e)
		{
			throw e; 
		}
	}

	private void showFilterConfig() throws Exception {
		try
		{
			if (picturePane.filter != null && picturePane.filter.attributes != null) {			
			FilterConfig f = new FilterConfig(mainFrame, picturePane.filter);
			f.setVisible(true);
		}
		}
		catch(Exception e)
		{
			throw e;
		}
	}

	private void closeCase() throws Exception{ 
		try
		{
		DefaultMutableTreeNode node = (DefaultMutableTreeNode)caseTree.getLastSelectedPathComponent();
		if(node != null && !node.isLeaf() && !node.isRoot()) {
			// Case node
			Case c = (Case)node.getUserObject();
			treeModel.removeNodeFromParent(node);
			serverConnection.CheckinCase(c);
		}
		}
		catch(Exception e)
		{
			throw e;
		}
	}
    /*
     * Ravi 
     */
	private void openCase() throws Exception {
		try
		{
			if (serverConnection != null) 
			{
				System.out.print("serverconnection is not null");
				Vector<Case> caseList = serverConnection.GetCases(); //case 1,case 2,case3
				CaseBrowser cb = new CaseBrowser(mainFrame, caseList);
				cb.pack();
				cb.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
				cb.setVisible(true);
				Vector<Case> cases = cb.GetCases();
				
				if (cases != null) 
				{
					for(Case c: cases) 
					{
						///////// FIX  3 --  8 - 11 - 2011 ///////
						if(!CaseAvailable(c))
                        {
                               JOptionPane.showMessageDialog(new JFrame(), c.name +" is already opened.");
                        }
						else
						{
							AddCase(c);
						}
					}
				}
			}
			else
				System.out.println(" serverconnection is null ");
		}
		catch(Exception e)
		{
			throw e;
		}
}
	// AS a part of the fix 3
	private boolean CaseAvailable(Case c) throws Exception
    {
           boolean caseAvailable = false;
           
           // Get Available Cases from server
           Vector<Case> availableCaseList = serverConnection.GetCases();
           
           for(Case cs: availableCaseList)
           {
                  if(cs.id == c.id)
                  {
                        caseAvailable = true;
                        break;
                  }
           }
           
           return caseAvailable;
    }

	private void handleServerConnect() throws Exception 
	{
		try 
		{
			System.out.println("handleServerConnect  : in ");
		/*String address = (String) JOptionPane.showInputDialog(mainFrame, 
				"Enter the Server Address to connect to", 
				"Connect", 
				JOptionPane.PLAIN_MESSAGE,
				(Icon)null, null, "localhost");
				*/
		ConnectionDialog cd = new ConnectionDialog(this.mainFrame);
		cd.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
		cd.setVisible(true);
		
		if(!cd.canceled) 
		{
			String address = cd.addr.getText();
			System.out.println("IP Address:"+address);
			
			//serverConnection = new PPServerConnection(this, address, cd.docid.getText());
	    	serverConnection = PPServerConnection.getInstance(this, address, cd.docid.getText());
	    	connectServerItem.setEnabled(false);
		 }
		}
		catch (Exception e)
		{
			throw e;
		}
	}

	private void createClientSocket(String address) {		
		try {
			clientSocket = new Socket(address, 42420);
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
    /*
     * Ravi :Checked
     */
	private void handleQuit() throws Exception {
		try
		{
			CleanupAndExit();
		}
		catch(Exception e)
		{
			throw e;
		}
		
	}

	/*
	 * Ravi 
	 */
	public void AddCase(Case c) throws Exception 
	{		
		try
		{
			System.out.println("Opening case:"+c.name);

		DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(c);		
		treeModel.insertNodeInto(childNode, rootNode, rootNode.getChildCount());			
		
		Vector<PPImage> imageList = serverConnection.GetImagesForCase(c);
		for(PPImage img:imageList) 
		{
			System.out.println(" img ");
			DefaultMutableTreeNode imgNode = new DefaultMutableTreeNode(img);
			treeModel.insertNodeInto(imgNode,childNode, childNode.getChildCount());				
		}
		
		serverConnection.CheckoutCase(c);
		
		TreePath tp = new TreePath(childNode.getPath());
		caseTree.scrollPathToVisible(tp);
		}
		catch(Exception e)
		{
			throw e;
		}
	}

	public void valueChanged(TreeSelectionEvent ev) 
	{
		try
		{
			DefaultMutableTreeNode node = (DefaultMutableTreeNode)
			caseTree.getLastSelectedPathComponent();

		if (node == null)
			//Nothing is selected.	
			return;
		
		Object nodeInfo = node.getUserObject();
		if (node.isLeaf() && !node.isRoot()) 
		{
			System.out.println("node is leaf not root");
			PPImage img = (PPImage)nodeInfo;// PPImage object is created
			Case c = (Case)((DefaultMutableTreeNode)node.getParent()).getUserObject();
			serverConnection.GetImageData(img);
			Patient p = serverConnection.GetPatient(c.patientid);
			picturePane.ShowImage(img, p);				
		} else 
		{
			System.out.println("node is root");
		}
		}
		catch(Exception e )
		{
			try {
				throw e;
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
}
